package com.stars.system.reim.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelCellInfo;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.utils.poi.WordUtil;
import com.ruoyi.common.utils.uuid.UUID;
import com.ruoyi.system.service.ISysUserService;
import com.stars.system.reim.domain.*;
import com.stars.system.reim.mapper.ReimDailyRecordMapper;
import com.stars.system.reim.mapper.ReimDailyStatMapper;
import com.stars.system.reim.service.IReimDailyRecordService;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 报销记录（个人）Service业务层处理
 * 
 * @author shuaibizhe
 * @date 2022-11-14
 */
@Service
public class ReimDailyRecordServiceImpl implements IReimDailyRecordService
{
    @Autowired
    private ReimDailyRecordMapper reimDailyRecordMapper;

    @Autowired
    private ReimDailyStatMapper reimDailyStatMapper;

    @Autowired
    private ISysUserService sysUserService;

    private static final Logger log = LoggerFactory.getLogger(ReimDailyRecordServiceImpl.class);

    private static String TEMPLATE_SRC = RuoYiConfig.getProfile() + "/template/reim/cover.xlsx";
    /**
     * 查询报销记录（个人）
     * 
     * @param reimId 报销记录（个人）主键
     * @return 报销记录（个人）
     */
    @Override
    public ReimDailyRecord selectReimDailyRecordByReimId(String reimId)
    {
        ReimDailyRecord reimRecord = reimDailyRecordMapper.selectReimDailyRecordByReimId(reimId);
        return reimRecord;
    }

    /**
     * 查询报销记录（个人）列表
     * 
     * @param reimRecord 报销记录
     * @return 报销记录
     */
    @Override
    public List<ReimDailyRecord> selectReimDailyRecordList(ReimDailyRecord reimRecord)
    {
        reimRecord = singleDataRange(reimRecord);
        return reimDailyRecordMapper.selectReimDailyRecordList(reimRecord);
    }

    /**
     * 查询报销记录（部门）列表
     *
     * @param reimRecord 报销记录
     * @param deptId 部门
     * @return 报销记录
     */
    @Override
    public List<ReimDailyRecord> selectReimRecordListByDept(ReimDailyRecord reimRecord, Long deptId)
    {
        reimRecord = singleDataRange(reimRecord);
        return reimDailyRecordMapper.selectReimRecordListByDept(reimRecord, deptId);
    }

    /**
     * 新增报销记录（个人）
     * 
     * @param reimRecord 报销记录（个人）
     * @return 结果
     */
    @Override
    public int insertReimDailyRecord(ReimDailyRecord reimRecord)
    {
        reimRecord.setCreateTime(DateUtils.getNowDate());
        reimRecord.setReimId(UUID.fastUUID().toString());
        return reimDailyRecordMapper.insertReimDailyRecord(reimRecord);
    }

    /**
     * 修改报销记录（个人）
     * 
     * @param reimRecord 报销记录（个人）
     * @return 结果
     */
    @Override
    public int updateReimDailyRecord(ReimDailyRecord reimRecord)
    {
        return reimDailyRecordMapper.updateReimDailyRecord(reimRecord);
    }

    /**
     * 批量删除报销记录（个人）
     * 
     * @param reimIds 需要删除的报销记录（个人）主键
     * @return 结果
     */
    @Override
    public int deleteReimDailyRecordByReimIds(String[] reimIds)
    {
        return reimDailyRecordMapper.deleteReimDailyRecordByReimIds(reimIds);
    }

    /**
     * 删除报销记录（个人）信息
     * 
     * @param reimId 报销记录（个人）主键
     * @return 结果
     */
    @Override
    public int deleteReimRecordByReimId(String reimId)
    {
        return reimDailyRecordMapper.deleteReimRecordByReimId(reimId);
    }

    /**
     * 统计前确认数据
     *
     * @param reimIds 报销记录（个人）主键
     * @return 结果
     */
    @Override
    public boolean confirmDailyBeforeStat(String[] reimIds, int cycle)
    {
        int count = reimDailyRecordMapper.confirmDailyBeforeStat(reimIds, cycle);
        if (count > 0) {
            return false;
        }
        return true;
    }

    /**
     * 统计数据
     *
     * @param reimIds 报销记录（个人）主键
     * @return 结果
     */
    @Override
    public List statReimDailyRecord(String[] reimIds)
    {
        List<ReimDailyStatInfo> stats = reimDailyRecordMapper.statReimDailyRecord(reimIds);
        if (stats.size() == 0) {
            return new ArrayList();
        }
        // 计算总计
        ReimDailyStatInfo totalStat = new ReimDailyStatInfo();
        for (ReimDailyStatInfo stat : stats) {
            totalStat.sumStat(stat);
        }
        stats.add(totalStat);
        return stats;
    }

    /**
     * 生成支付记录word文档
     * @param reimIds
     * @param response
     * @param request
     * @throws IOException
     * @throws InvalidFormatException
     */
    @Override
    public void exportReimDailyRecordImgs(String[] reimIds, HttpServletResponse response, HttpServletRequest request) {
        log.info("导出支付记录 word 文档--------------------------");
        List<ReimDailyRecord> records = reimDailyRecordMapper.selectReimDailyRecordByReimIds(reimIds);
        WordUtil wordUtil = new WordUtil();
        wordUtil.init();
        StringBuilder missImg = new StringBuilder();
        for (ReimDailyRecord reimRecord : records) {
            if (StringUtils.isEmpty(reimRecord.getReimImg())) {
                continue;
            }
            // 找到图片的真实路径
            String imgSrc = reimRecord.getReimImg().replaceAll("/profile", RuoYiConfig.getProfile());
            try {
                if (imgSrc.contains(",")) {
                    wordUtil.addPictures(imgSrc.split(","), 136, 309);
                } else {
                    wordUtil.addPicture(imgSrc, 136, 309);
                }
            } catch (IOException | InvalidFormatException exception) {
                missImg.append("未找到图片：")
                        .append("      ")
                        .append("报销人：").append(sysUserService.selectUserById(reimRecord.getReimSpender()).getNickName())
                        .append("，报销时间：").append(DateUtils.parseDateToStr("yyyy-MM-dd",reimRecord.getReimDate()))
                        .append("\r\n");
                continue;
            }
        }
        wordUtil.setText(missImg.toString());
        String fileName = "报销支付记录_" + DateUtils.getDate() + ".docx";
        wordUtil.exportWord(fileName, response);
    }

    /**
     * 生成报销封面excel
     * @param reimIds
     * @param response
     * @param request
     * @throws IOException
     * @throws InvalidFormatException
     */
    @Override
    public void exportReimDailyRecordCover(String[] reimIds, HttpServletResponse response, HttpServletRequest request) throws IOException, InvalidFormatException {
        log.info("导出报销封面 excel 文档--------------------------");
        List<ReimDailyRecord> records = reimDailyRecordMapper.selectReimDailyRecordByReimIdsAndType(reimIds, DictUtils.getDictValue("reim_type", "餐费"));
        File template = new File(TEMPLATE_SRC);
        FileInputStream fileInputStream = new FileInputStream(template);
        ExcelUtil excelUtil = new ExcelUtil<>(ReimDailyRecordServiceImpl.class);
        excelUtil.createSheetByTemplate(fileInputStream);

        int count = 1;
        int insertLocate = 6;
        excelUtil.shiftRows(insertLocate + 1, insertLocate + 2, records.size());
        BigDecimal sumAmount = new BigDecimal(0);
        for (ReimDailyRecord record : records) {
            excelUtil.createRowFillCell(insertLocate, List.of(
                    new ExcelCellInfo(0, Integer.class, count),
                    new ExcelCellInfo(1, String.class, DateUtils.parseDateToStr("yyyy-MM-dd",record.getReimDate())),
                    new ExcelCellInfo(2, String.class, sysUserService.selectUserById(record.getReimSpender()).getNickName() + (record.getReimUser() != null ? "、" + record.getReimUser() : "")),
                    new ExcelCellInfo(3, String.class, "济南"),
                    new ExcelCellInfo(4, Integer.class, record.getReimUser() != null ? record.getReimUser().split("、").length + 1 : 1),
                    new ExcelCellInfo(5, Double.class, record.getReimAmountDouble())
            ));
            sumAmount = sumAmount.add(record.getReimAmount());
            count++;
            insertLocate++;
        }
        excelUtil.getRowFillCell(insertLocate + 1, List.of(
                new ExcelCellInfo(3, Integer.class, count - 1),
                new ExcelCellInfo(5, Double.class, Double.valueOf(String.valueOf(sumAmount)))
        ));
        excelUtil.exportExcel("cover.xlsx", response);
    }

    /**
     * 将数据标记为报销完成
     *
     * @param reimIds 报销记录（个人）主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int completeReimDailyRecord(String[] reimIds) {
        String statId = UUID.fastUUID().toString();
        List<ReimDailyStatInfo> stats = reimDailyRecordMapper.statReimDailyRecord(reimIds);
        // 计算总计
        ReimDailyStatInfo totalStat = new ReimDailyStatInfo();
        for (ReimDailyStatInfo stat : stats) {
            totalStat.sumStat(stat);
        }
        stats.add(totalStat);
        reimDailyStatMapper.insertReimDailyStat(new ReimDailyStat(statId, DateUtils.getNowDate(), JSONArray.toJSONString(stats)));
        return reimDailyRecordMapper.completeReimDailyRecord(reimIds, statId);
    }

    /**
     * 时间范围查询，单个时间
     * @param reimRecord
     * @return
     */
    private ReimDailyRecord singleDataRange(ReimDailyRecord reimRecord) {
        // 时间范围插件 只选择单个时间时 当作单个时间查询
        if (reimRecord == null || CollectionUtils.isEmpty(reimRecord.getParams()) || (reimRecord.getParams().get("beginTime") == null && reimRecord.getParams().get("endTime") == null)) {
            return reimRecord;
        }

        if (reimRecord.getParams().get("beginTime") == null) {
            reimRecord.getParams().put("beginTime", reimRecord.getParams().get("endTime"));
        } else if (reimRecord.getParams().get("endTime") == null) {
            reimRecord.getParams().put("endTime", reimRecord.getParams().get("beginTime"));
        }

        return reimRecord;
    }

    /**
     * 查询逾期记录数量
     *
     * @param cycle 逾期周期
     * @return 结果
     */
    @Override
    public List<ReimDailyOverdue> countDailyOverdueRecords(int cycle) {
        return reimDailyRecordMapper.countDailyOverdueRecords(cycle, SecurityUtils.getUserId());
    }

    /**
     * 根据年月进行记录聚合，用于统计每月报销情况
     * @return
     */
    @Override
    public List<ReimDailyRecordVO> buildRecordsByMonthGroup(List<ReimDailyRecord> records) {
        Set months = new HashSet();
        List<ReimDailyRecordVO> result = new ArrayList();
        ReimDailyRecordVO recordVO = new ReimDailyRecordVO();
        for (ReimDailyRecord record : records) {
            String month = DateUtils.parseDateToStr("yyyy-MM", record.getReimDate());
            // 存在当前年月则累加，不存在则新增
            if (months.contains(month)) {
                recordVO.addRecord(record);
            } else {
                // 统计当月支出情况，及是否是连续下拉数据
                result.add(recordVO);
                ReimDailyRecordVO statInfo = reimDailyRecordMapper.buildRecordsByMonthGroup(month, record.getReimDate(), SecurityUtils.getUserId());
                recordVO = new ReimDailyRecordVO();
                recordVO.buildReimRecordVO(statInfo.getCount() > 0 ? null : month, statInfo);
                recordVO.addRecord(record);
                months.add(month);
            }
        }
        result.add(recordVO);
        // 剔除第一个多余数据
        result.remove(0);
        return result;
    }
}
